package qiniu

import (
	"bytes"
	"context"
	"io"
	"io/ioutil"
	"os"
	"time"

	"github.com/qiniu/api.v7/auth/qbox"
	"github.com/qiniu/api.v7/storage"
)

type Entity struct {
	Key    string //key
	Secret string //secret
	Domain string //前缀
	Space  string //空间
	err    error  //错误
}

// New 新建七牛
// @key ,key
// @secret ,secret
// @url ,url,例如"http://qnc.qjnice.com/"
// @space ,储存空间,例如 "qjpublic"
func New(key, secret, url, space string) *Entity {
	return &Entity{
		Key:    key,
		Secret: secret,
		Domain: url,
		Space:  space,
	}
}

func Def() *Entity {
	return New(
		defKey,
		defSecret,
		defDomain,
		defSpace,
	)
}

// SetKey 设置key
func (this *Entity) SetKey(key string) *Entity {
	this.Key = key
	return this
}

// SetSecret 设置Secret
func (this *Entity) SetSecret(secret string) *Entity {
	this.Secret = secret
	return this
}

// SetSpace 设置七牛空间地址
func (this *Entity) SetSpace(space string) *Entity {
	this.Space = space
	return this
}

// SetDomain 例如"https://qnc.qjnice.com/"
func (this *Entity) SetDomain(domain string) *Entity {
	this.Domain = domain
	return this
}

func (this *Entity) SetErr(err error) *Entity {
	if this.err == nil {
		this.err = err
	}
	return this
}

//===============================================

// GetPrivateURL 七牛云，获取私有下载URL,有效期1小时
func (this *Entity) GetPrivateURL(key string) string {
	mac := qbox.NewMac(this.Key, this.Secret)
	deadline := time.Now().Add(time.Second * 3600).Unix() //1小时有效期
	return storage.MakePrivateURL(mac, this.Domain, key, deadline)
}

// GetPrivateToken 七牛云，获取私有上传Token
func (this *Entity) GetPrivateToken() string {
	putPolicy := storage.PutPolicy{
		Scope: this.Space,
	}
	mac := qbox.NewMac(this.Key, this.Secret)
	upToken := putPolicy.UploadToken(mac)
	return upToken
}

//===============================================

// Save 上传数据
// @name,名称
// @r,读数据流
func (this *Entity) Save(name string, r io.Reader) (string, error) {
	if this.err != nil {
		return "", this.err
	}
	bs, err := ioutil.ReadAll(r)
	if err != nil {
		return "", err
	}
	buff := bytes.NewBuffer(bs)
	mac := qbox.NewMac(this.Key, this.Secret)
	putPolicy := storage.PutPolicy{Scope: this.Space}
	upToken := putPolicy.UploadToken(mac)
	cfg := storage.Config{
		Zone:          &storage.ZoneHuadong, // 空间对应的机房
		UseHTTPS:      false,                // 是否使用https域名
		UseCdnDomains: false,                // 上传是否使用CDN上传加速
	}
	formUploader := storage.NewFormUploader(&cfg)
	ret := storage.PutRet{}
	err = formUploader.Put(context.Background(), &ret, upToken, name, buff, int64(buff.Len()), new(storage.PutExtra))
	return this.Domain + ret.Key, err
}

// UploadBytes 上传字节数组
// @name,名称
// @bs,字节数组内容
func (this *Entity) UploadBytes(name string, bs []byte) (string, error) {
	return this.Save(name, bytes.NewBuffer(bs))
}

// UploadLocal 上传七牛私有方法
// @path,本地文件路径
// @name,文件名称
func (this *Entity) UploadLocal(name, path string) (string, error) {
	f, err := os.Open(path)
	this.SetErr(err)
	return this.Save(name, f)
}

// UploadReader 上传数据读取流
// @path,本地文件路径
// @r,数据读取流
func (this *Entity) UploadReader(name string, r io.Reader) (string, error) {
	return this.Save(name, r)
}
